'use client';

import type { TBody, TMetadata } from '@/types';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
  applyOauthClientApi,
  createOauthClient,
  deleteOauthClient,
  queryOauthClientApis,
  queryOauthClientsByUser,
  queryOauthClientSecretById,
  updateOauthClientById,
  updateOauthClientSecretById,
} from '@/services/api';
import type {
  IApplyOauthClientApiBody,
  ICreateOauthClientBody,
  IDifference,
  IOauthClient,
  IOauthClientApi,
  IUpdateOauthClientByIdBody,
} from '@/interfaces';
import ErrorPage from '@/app/[locale]/error/error';
import LoadPage from '@/app/[locale]/load/load';
import {
  type ChangeEvent,
  type Dispatch,
  type FormEvent,
  type SetStateAction,
  useEffect,
  useRef,
  useState,
} from 'react';
import useToast from '@/hooks/useToast';
import diff from 'microdiff';
import Link from 'next/link';
import { OAUTH_CLIENT_REVIEW_STATE_KEY } from '@/lib/constant';
import Image from 'next/image';
import useUser from '@/hooks/useUser';
import { formatTime } from '@/lib/tool';
import { NavbarPage } from '@/app/[locale]/navbar';
import FooterPage from '@/app/[locale]/footer';
import { useTranslations } from 'use-intl';

export default function OauthClientPage({ metadata }: { metadata: TMetadata }) {
  return (
    <>
      <NavbarPage metadata={metadata} />
      <Client metadata={metadata} />;
      <FooterPage metadata={metadata} />
    </>
  );
}

const Client = ({ metadata }: { metadata: TMetadata }) => {
  const t = useTranslations('OauthPage');
  const userQuery = useUser(metadata);
  const [isOpen, setIsOpen] = useState(false);
  const { show } = useToast();

  function onClickCreateClient() {
    setIsOpen(!isOpen);
  }

  function onClickViewDoc() {
    show({
      type: 'INFO',
      message: t('accessDocNotExist'),
    });
  }

  return (
    <div className="col px-0">
      <div className="card border-0">
        <div className="card-body">
          <div className="container-fluid p-2 py-4 vstack gap-4">
            <div className="d-flex justify-content-between align-items-center">
              <div className="h5">
                <span>{t('authClient')}</span>
                {userQuery.data && userQuery.data.clientConfig?.doc ? (
                  <span>
                    （
                    <Link
                      href={userQuery.data.clientConfig.doc}
                      className="text-decoration-none text-decoration-underline-hover text-secondary"
                    >
                      {t('viewAccessDoc')}
                    </Link>
                    ）
                  </span>
                ) : (
                  <span>
                    （
                    <a
                      onClick={onClickViewDoc}
                      className="text-decoration-none text-decoration-underline-hover text-secondary cursor-pointer"
                    >
                      {t('viewAccessDoc')}
                    </a>
                    ）
                  </span>
                )}
              </div>
              <div className="hstack gap-4">
                {isOpen ? (
                  <button
                    onClick={onClickCreateClient}
                    type="button"
                    className="btn btn-light"
                  >
                    <i className="bi bi-x-lg me-2"></i>
                    {t('closeCreate')}
                  </button>
                ) : (
                  <button
                    onClick={onClickCreateClient}
                    type="button"
                    className="btn btn-primary"
                  >
                    <i className="bi bi-plus-lg me-2"></i>
                    {t('createApp')}
                  </button>
                )}
              </div>
            </div>
            <div>
              {isOpen && (
                <CreateClient setIsOpen={setIsOpen} metadata={metadata} />
              )}
            </div>
            <div>
              <Clients metadata={metadata} setIsOpen={setIsOpen} />
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

const CreateClient = ({
  setIsOpen,
  metadata,
}: {
  setIsOpen: Dispatch<SetStateAction<boolean>>;
  metadata: TMetadata;
}) => {
  const t = useTranslations('OauthPage');
  const [form, setForm] = useState({
    name: '',
    website: '',
    callback: '',
  });
  const [isSave, setIsSave] = useState(true);
  const [differenceData, setDifferenceData] = useState<IDifference[]>([]);
  const { show } = useToast();
  const queryClient = useQueryClient();

  const createOauthClientMutation = useMutation(
    async (variables: TBody<ICreateOauthClientBody>) => {
      await createOauthClient(variables);
    },
  );

  useEffect(() => {
    const differences = diff(
      {
        name: '',
        website: '',
        callback: '',
      },
      form,
    );
    setIsSave(!differences.length);
    setDifferenceData(differences);
  }, [form]);

  async function onSubmit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    e.stopPropagation();

    try {
      checkForm();
      await createOauthClientMutation.mutateAsync({
        data: form,
      });
      await queryClient.refetchQueries(
        metadata.all['clients'].k,
        {},
        { throwOnError: true },
      );
      clearData();
      show({
        type: 'SUCCESS',
        message: t('saveComplete'),
      });
    } catch (e) {
      createOauthClientMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onChange(e: ChangeEvent<HTMLInputElement>) {
    const name = e.target.name;
    const value = e.target.value;
    setForm({ ...form, [name]: value.trim() });
  }

  function checkForm() {
    const { name, website, callback } = form;
    if (!name) {
      throw t('enterAppName');
    }

    if (!website) {
      throw t('enterAppSite');
    }

    if (!callback) {
      throw t('enterAppCallback');
    }
  }

  function clearData() {
    setForm({
      name: '',
      website: '',
      callback: '',
    });
    setIsSave(true);
    setDifferenceData([]);
    setIsOpen(false);
  }

  return (
    <div className="card">
      <div className="card-body">
        <form className="vstack gap-4" onSubmit={onSubmit}>
          <div className="">
            <label className="form-label">{t('appName')}</label>
            <input
              name="name"
              value={form.name}
              onChange={onChange}
              type="text"
              className="form-control"
              placeholder={t('inputAppName')}
            />
          </div>

          <div className="">
            <label className="form-label">{t('appSite')}</label>
            <input
              name="website"
              value={form.website}
              onChange={onChange}
              type="url"
              className="form-control"
              placeholder={t('enterAppSite')}
            />
            <div className="form-text">{t('siteOnlySupportHttpHttps')}</div>
          </div>

          <div className="">
            <label className="form-label">{t('appCallback')}</label>
            <input
              name="callback"
              value={form.callback}
              onChange={onChange}
              type="url"
              className="form-control"
              placeholder={t('enterAppCallback')}
            />
            <div className="form-text">{t('callbackOnlySupportHttpHttps')}</div>
          </div>

          <div>
            <div className="form-text text-muted ">
              <i className="bi bi-info-circle me-2"></i>
              <ol>
                <li>{t('appInReview')}</li>
                <li>{t('callbackChangeNeedReview')}</li>
                <li>{t('defaultOpenAuthAccess')}</li>
              </ol>
            </div>
          </div>

          <div className="text-center mt-4 mb-3">
            <button
              type="submit"
              disabled={isSave || createOauthClientMutation.isLoading}
              className="btn btn-primary"
            >
              {createOauthClientMutation.isLoading ? (
                <span
                  className="spinner-border spinner-border-sm me-2"
                  role="status"
                  aria-hidden="true"
                ></span>
              ) : (
                <i className="bi bi-save me-2"></i>
              )}
              {t('saveApp')}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
};

const Clients = ({
  metadata,
  setIsOpen,
}: {
  metadata: TMetadata;
  setIsOpen: Dispatch<SetStateAction<boolean>>;
}) => {
  const t = useTranslations('OauthPage');
  const [currentId, setCurrentId] = useState<number>();
  const [currentItem, setCurrentItem] = useState<IOauthClient>();
  const [currentItem2, setCurrentItem2] = useState<IOauthClient>();
  const [isOpenAppSecret, setIsOpenAppSecret] = useState(false);
  const [isOpenUpdate, setIsOpenUpdate] = useState(false);
  const [isOpenInterface, setIsOpenInterface] = useState(false);
  const nameInputRef = useRef<HTMLInputElement>(null);
  const logoInputRef = useRef<HTMLTextAreaElement>(null);
  const overviewInputRef = useRef<HTMLTextAreaElement>(null);
  const websiteInputRef = useRef<HTMLTextAreaElement>(null);
  const callbackInputRef = useRef<HTMLTextAreaElement>(null);
  const userQuery = useUser(metadata);
  const { show } = useToast();

  const queryOauthClientsByUserQuery = useQuery(
    metadata.all['clients'].k,
    async () => {
      return (await queryOauthClientsByUser()) as IOauthClient[];
    },
    {
      initialData: metadata.all['clients'].v as IOauthClient[],
    },
  );
  const queryOauthClientSecretByIdQuery = useQuery(
    ['/oauth', '/clients', currentId, '/secret'],
    async (context) => {
      try {
        return (await queryOauthClientSecretById({
          id: context.queryKey[2] + '',
        })) as string;
      } catch (e) {
        show({
          type: 'DANGER',
          message: e,
        });
        throw e;
      }
    },
    {
      enabled: isOpenAppSecret && !!currentId,
    },
  );
  const queryOauthClientApisQuery = useQuery(
    ['/oauth', '/clients', '/apis', { cid: currentItem2?.id }],
    async (context) => {
      try {
        return (await queryOauthClientApis({
          query: (context.queryKey[3] || {}) as {},
        })) as IOauthClientApi[];
      } catch (e) {
        show({
          type: 'DANGER',
          message: e,
        });
        throw e;
      }
    },
    {
      enabled: isOpenInterface && !!currentItem2,
    },
  );

  const updateOauthClientSecretByIdMutation = useMutation(
    async (variables: TBody<void>) => {
      await updateOauthClientSecretById(variables);
    },
  );
  const updateOauthClientByIdMutation = useMutation(
    async (variables: TBody<IUpdateOauthClientByIdBody>) => {
      await updateOauthClientById(variables);
    },
  );
  const applyOauthClientApiMutation = useMutation(
    async (variables: TBody<IApplyOauthClientApiBody>) => {
      await applyOauthClientApi(variables);
    },
  );
  const deleteOauthClientMutation = useMutation(
    async (variables: TBody<void>) => {
      await deleteOauthClient(variables);
    },
  );

  async function onClickSecret(item: IOauthClient) {
    setCurrentId(item.id);
    setIsOpenAppSecret(!isOpenAppSecret);
  }

  async function onClickResetSecret(item: IOauthClient) {
    try {
      setCurrentId(item.id);

      await updateOauthClientSecretByIdMutation.mutateAsync({
        id: item.id,
      });

      if (isOpenAppSecret) {
        await queryOauthClientSecretByIdQuery.refetch({
          throwOnError: true,
        });
      } else {
        setTimeout(() => {
          show({
            type: 'PRIMARY',
            message: t('appSecretTip'),
          });
        }, 2500);
      }

      show({
        type: 'SUCCESS',
        message: t('resetAppSecretComplete'),
      });
    } catch (e) {
      updateOauthClientSecretByIdMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onClickUpdate(item: IOauthClient) {
    setCurrentItem(item);
    setIsOpenUpdate(!isOpenUpdate);
  }

  async function onClickSaveUpdate(item: IOauthClient) {
    try {
      if (!currentItem) {
        show({
          type: 'DANGER',
          message: t('failToGetAppInfo'),
        });
        return;
      } else if (currentItem.id !== item.id) {
        show({
          type: 'DANGER',
          message: t('failToSaveInfo'),
        });
        return;
      }

      const inputValue = getInputValue();

      if (!Object.values(inputValue).filter((value) => value).length) {
        show({
          type: 'INFO',
          message: t('saveAppInfoComplete'),
        });
        cleanData();
        return;
      }

      if (
        inputValue.name === item.name &&
        inputValue.overview === (item.overview || '') &&
        inputValue.logo === (item.logo || '') &&
        inputValue.website === (item.website || '') &&
        inputValue.callback === item.callback
      ) {
        show({
          type: 'INFO',
          message: t('saveAppInfoComplete'),
        });
        cleanData();
        return;
      }

      await updateOauthClientByIdMutation.mutateAsync({
        id: item.id,
        data: inputValue,
      });
      await queryOauthClientsByUserQuery.refetch({ throwOnError: true });
      cleanData();

      show({
        type: 'SUCCESS',
        message: t('saveAppInfoComplete'),
      });
    } catch (e) {
      updateOauthClientByIdMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onClickInterface(item: IOauthClient) {
    setCurrentItem2(item);
    setIsOpenInterface(!isOpenInterface);
  }

  async function onClickOpenInterface(
    item: IOauthClient,
    apiItem: IOauthClientApi,
  ) {
    try {
      if (apiItem.reviewState === 'SUCCESSFUL') {
        show({
          type: 'PRIMARY',
          message: t('accessGranted'),
        });
        return;
      }

      if (apiItem.reviewState === 'PENDING') {
        show({
          type: 'INFO',
          message: t('inReviewQueue'),
        });
        return;
      }

      await applyOauthClientApiMutation.mutateAsync({
        id: item.id,
        data: {
          apiId: apiItem.id + '',
        },
      });
      await queryOauthClientApisQuery.refetch({ throwOnError: true });

      show({
        type: 'SUCCESS',
        message: t('submitApplyComplete'),
      });
    } catch (e) {
      applyOauthClientApiMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  async function onClickRemove(item: IOauthClient) {
    try {
      setCurrentId(item.id);

      await deleteOauthClientMutation.mutateAsync({
        id: item.id,
      });
      await queryOauthClientsByUserQuery.refetch({ throwOnError: true });

      show({
        type: 'SUCCESS',
        message: t('deleteAppComplete'),
      });
    } catch (e) {
      deleteOauthClientMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onClickApiItemName() {
    show({
      type: 'INFO',
      message: t('noDocAvailable'),
    });
  }

  function onClickAppName(item: IOauthClient) {
    onClickUpdate(item);
  }

  function onClickAppOther(item: IOauthClient) {
    onClickInterface(item);
  }

  function getInputValue() {
    return {
      name: nameInputRef.current?.value.trim(),
      overview: overviewInputRef.current?.value.trim(),
      logo: logoInputRef.current?.value.trim(),
      website: websiteInputRef.current?.value.trim(),
      callback: callbackInputRef.current?.value.trim(),
    };
  }

  function cleanData() {
    setIsOpenUpdate(false);
    setCurrentItem(undefined);
  }

  function onClickCreateApp() {
    setIsOpen(true);
  }

  if (queryOauthClientsByUserQuery.data) {
    return (
      <div className="card">
        <div className="card-body">
          <div className="table-responsive">
            <table className="table">
              <caption className="text-muted small mt-4 text-end">
                <i className="bi bi-info-circle me-2"></i>
                <span>{t('haveIssues')}&nbsp;</span>
                <Link
                  className="text-decoration-none text-decoration-underline-hover text-secondary"
                  href={
                    userQuery.data && userQuery.data ? '/posts/new' : '/login'
                  }
                >
                  {t('tryPost')}
                </Link>
              </caption>
              <thead>
                <tr>
                  <th scope="col">{t('appID')}</th>
                  <th scope="col">{t('name')}</th>
                  <th scope="col">{t('status')}</th>
                  <th scope="col">{t('create')}</th>
                  <th scope="col" style={{ width: 500 }}>
                    {t('operate')}
                  </th>
                </tr>
              </thead>
              <tbody>
                {queryOauthClientsByUserQuery.data.map((item) => {
                  return (
                    <tr key={item.id} className="align-middle">
                      {isOpenUpdate ? (
                        <td colSpan={4}>
                          <table className="table table-borderless">
                            <tbody>
                              <tr className="align-middle">
                                <th className="text-nowrap">{t('appID')}</th>
                                <td className="text-nowrap">
                                  <input
                                    disabled
                                    value={item.clientId}
                                    className="form-control"
                                    type="text"
                                    aria-label="clientId"
                                  />
                                </td>
                              </tr>
                              <tr className="align-middle">
                                <th className="text-nowrap">{t('name')}</th>
                                <td className="text-nowrap">
                                  <input
                                    ref={nameInputRef}
                                    defaultValue={item.name}
                                    className="form-control"
                                    type="text"
                                    aria-label="name"
                                  />
                                </td>
                              </tr>
                              <tr className="align-middle">
                                <th className="text-nowrap">{t('overview')}</th>
                                <td className="text-nowrap">
                                  <textarea
                                    ref={overviewInputRef}
                                    defaultValue={item.overview || ''}
                                    className="form-control"
                                    rows={1}
                                    aria-label="overview"
                                  />
                                </td>
                              </tr>
                              <tr className="align-middle">
                                <th className="text-nowrap">{t('iconUrl')}</th>
                                <td className="text-nowrap">
                                  <textarea
                                    ref={logoInputRef}
                                    defaultValue={item.logo || ''}
                                    className="form-control"
                                    rows={1}
                                    aria-label="logo"
                                  />
                                </td>
                              </tr>
                              <tr className="align-middle">
                                <th className="text-nowrap">{t('siteUrl')}</th>
                                <td className="text-nowrap">
                                  <textarea
                                    ref={websiteInputRef}
                                    defaultValue={item.website || ''}
                                    className="form-control"
                                    rows={1}
                                    aria-label="website"
                                  />
                                </td>
                              </tr>
                              <tr className="align-middle">
                                <th className="text-nowrap">
                                  {t('callbackAddress')}
                                </th>
                                <td className="text-nowrap">
                                  <textarea
                                    ref={callbackInputRef}
                                    defaultValue={item.callback}
                                    className="form-control"
                                    rows={1}
                                    aria-label="callback"
                                  />
                                  <div className="form-text text-muted">
                                    <i className="bi bi-info-circle me-2"></i>
                                    {t('needReapprovalOnCallbackChange')}
                                  </div>
                                </td>
                              </tr>
                              <tr className="align-middle">
                                <th className="text-nowrap"></th>
                                <td className="text-nowrap text-center">
                                  <button
                                    disabled={
                                      currentItem &&
                                      item.id === currentItem.id &&
                                      updateOauthClientByIdMutation.isLoading
                                    }
                                    onClick={onClickSaveUpdate.bind(this, item)}
                                    type="button"
                                    className="btn btn-primary"
                                  >
                                    {currentItem &&
                                    item.id === currentItem.id &&
                                    updateOauthClientByIdMutation.isLoading ? (
                                      <span
                                        className="spinner-border spinner-border-sm me-2"
                                        role="status"
                                        aria-hidden="true"
                                      ></span>
                                    ) : (
                                      <i className="bi bi-save me-2"></i>
                                    )}
                                    {t('saveInfo')}
                                  </button>
                                </td>
                              </tr>
                            </tbody>
                          </table>
                        </td>
                      ) : (
                        <>
                          {isOpenInterface ? (
                            <td colSpan={4}>
                              <table className="table table-borderless">
                                <thead className="table-light">
                                  <tr>
                                    <th scope="col">{t('function')}</th>
                                    <th scope="col">{t('interface')}</th>
                                    <th scope="col">
                                      {t('dailyCallVolume')}&nbsp;/&nbsp;
                                      {t('limit')}
                                    </th>
                                    <th scope="col">{t('status')}</th>
                                    <th scope="col" className="text-nowrap">
                                      {t('operate')}
                                    </th>
                                  </tr>
                                </thead>
                                <tbody>
                                  {queryOauthClientApisQuery.data &&
                                    queryOauthClientApisQuery.data.map(
                                      (apiItem) => {
                                        return (
                                          <tr
                                            key={apiItem.id}
                                            className="align-middle"
                                          >
                                            <td className="text-nowrap">
                                              {apiItem.category}
                                            </td>
                                            <td className="text-nowrap">
                                              {apiItem.doc ? (
                                                <Link
                                                  className="link-primary text-decoration-none text-decoration-underline-hover"
                                                  href={apiItem.doc}
                                                  target="_blank"
                                                >
                                                  {apiItem.overview ||
                                                    apiItem.name}
                                                </Link>
                                              ) : (
                                                <span
                                                  className="link-primary cursor-pointer text-decoration-underline-hover"
                                                  onClick={onClickApiItemName}
                                                >
                                                  {apiItem.overview ||
                                                    apiItem.name}
                                                </span>
                                              )}
                                            </td>
                                            <td className="text-nowrap text-secondary">
                                              <span>
                                                {apiItem.dailyCalls || 0}
                                              </span>
                                              <span>&nbsp;/&nbsp;</span>
                                              <span>
                                                {apiItem.upperLimit === 0
                                                  ? t('noLimit')
                                                  : apiItem.upperLimit}
                                              </span>
                                            </td>
                                            <td className="text-nowrap">
                                              {apiItem.type === 'DEFAULT' ||
                                              apiItem.reviewState ===
                                                'SUCCESSFUL' ? (
                                                <i
                                                  className="bi bi-patch-check-fill me-2 text-success fs-5"
                                                  title={t('granted')}
                                                ></i>
                                              ) : apiItem.reviewState ===
                                                'FAILED' ? (
                                                <i
                                                  className="bi bi-patch-check-fill me-2 text-danger fs-5"
                                                  title={t('notPassed')}
                                                ></i>
                                              ) : (
                                                <span>{t('notGranted')}</span>
                                              )}
                                            </td>
                                            <td className="text-nowrap">
                                              {apiItem.type === 'REQUIRED' &&
                                                apiItem.reviewState !==
                                                  'SUCCESSFUL' && (
                                                  <button
                                                    disabled={
                                                      (currentItem2 &&
                                                        item.id ===
                                                          currentItem2.id &&
                                                        applyOauthClientApiMutation.isLoading) ||
                                                      apiItem.reviewState ===
                                                        'PENDING'
                                                    }
                                                    onClick={onClickOpenInterface.bind(
                                                      this,
                                                      item,
                                                      apiItem,
                                                    )}
                                                    type="button"
                                                    className="btn btn-light"
                                                  >
                                                    {currentItem2 &&
                                                    item.id ===
                                                      currentItem2.id &&
                                                    applyOauthClientApiMutation.isLoading ? (
                                                      <span>
                                                        <span
                                                          className="spinner-border spinner-border-sm me-2"
                                                          role="status"
                                                          aria-hidden="true"
                                                        ></span>
                                                        <span>
                                                          {t('applyAccess')}
                                                        </span>
                                                      </span>
                                                    ) : (
                                                      <>
                                                        {apiItem.reviewState ===
                                                        'PENDING' ? (
                                                          <span>
                                                            {t('waitReview')}
                                                          </span>
                                                        ) : (
                                                          <span>
                                                            <i className="bi bi-patch-plus me-2"></i>
                                                            <span>
                                                              {t('applyAccess')}
                                                            </span>
                                                          </span>
                                                        )}
                                                      </>
                                                    )}
                                                  </button>
                                                )}
                                            </td>
                                          </tr>
                                        );
                                      },
                                    )}
                                </tbody>
                              </table>
                            </td>
                          ) : (
                            <>
                              <th
                                className="text-nowrap user-select-all"
                                scope="row"
                              >
                                {item.clientId}
                              </th>
                              <td
                                title={t('modifyAuthClient')}
                                onClick={onClickAppName.bind(this, item)}
                                className="text-nowrap cursor-pointer"
                              >
                                {item.logo ? (
                                  <Image
                                    className="object-fit-cover"
                                    src={item.logo}
                                    alt={item.name}
                                    title={item.name}
                                    width={32}
                                    height={32}
                                  />
                                ) : (
                                  <span>{item.name}</span>
                                )}
                              </td>
                              <td
                                title={t('viewInterfaceList')}
                                className="text-nowrap cursor-pointer"
                                onClick={onClickAppOther.bind(this, item)}
                              >
                                {item.reviewState === 'SUCCESSFUL' ? (
                                  <i
                                    className="bi bi-patch-check-fill me-2 text-success fs-5"
                                    title={t('passed')}
                                  ></i>
                                ) : item.reviewState === 'FAILED' ? (
                                  <i
                                    className="bi bi-patch-check-fill me-2 text-danger fs-5"
                                    title={t('notPassed')}
                                  ></i>
                                ) : (
                                  <span>
                                    {
                                      OAUTH_CLIENT_REVIEW_STATE_KEY[
                                        item.reviewState
                                      ]
                                    }
                                  </span>
                                )}
                              </td>
                              <td
                                title={t('viewInterfaceList')}
                                className="text-nowrap cursor-pointer"
                                onClick={onClickAppOther.bind(this, item)}
                              >
                                <time dateTime={item.createdOn}>
                                  {formatTime(item.createdOn)}
                                </time>
                              </td>
                            </>
                          )}
                        </>
                      )}

                      <td className="vstack gap-4 text-nowrap">
                        <div className="hstack gap-3">
                          <button
                            onClick={onClickUpdate.bind(this, item)}
                            type="button"
                            className="btn btn-light"
                          >
                            <i className="bi bi-pencil-square me-2"></i>
                            {isOpenUpdate ? t('cancel') : t('modify')}
                          </button>

                          <button
                            disabled={
                              isOpenInterface &&
                              currentItem2 &&
                              queryOauthClientApisQuery.isLoading
                            }
                            onClick={onClickInterface.bind(this, item)}
                            type="button"
                            className="btn btn-light"
                          >
                            {isOpenInterface &&
                            currentItem2 &&
                            queryOauthClientApisQuery.isLoading ? (
                              <span
                                className="spinner-border spinner-border-sm me-2"
                                role="status"
                                aria-hidden="true"
                              ></span>
                            ) : (
                              <i className="bi bi-door-open me-2"></i>
                            )}
                            {currentItem2 &&
                            isOpenInterface &&
                            !queryOauthClientApisQuery.isLoading
                              ? t('cancel')
                              : t('interface')}
                          </button>

                          <button
                            disabled={
                              currentId === item.id &&
                              isOpenAppSecret &&
                              queryOauthClientSecretByIdQuery.isLoading
                            }
                            onClick={onClickSecret.bind(this, item)}
                            type="button"
                            className="btn btn-light"
                          >
                            {currentId === item.id &&
                            isOpenAppSecret &&
                            queryOauthClientSecretByIdQuery.data ? (
                              <span>
                                <i className="bi bi-shield-shaded me-2"></i>
                                {t('hide')}
                              </span>
                            ) : (
                              <span>
                                {currentId === item.id &&
                                isOpenAppSecret &&
                                queryOauthClientSecretByIdQuery.isLoading ? (
                                  <span
                                    className="spinner-border spinner-border-sm me-2"
                                    role="status"
                                    aria-hidden="true"
                                  ></span>
                                ) : (
                                  <i className="bi bi-shield me-2"></i>
                                )}
                                {t('secret')}
                              </span>
                            )}
                          </button>

                          <button
                            disabled={
                              currentId === item.id &&
                              updateOauthClientSecretByIdMutation.isLoading
                            }
                            onClick={onClickResetSecret.bind(this, item)}
                            type="button"
                            className="btn btn-light"
                          >
                            {currentId === item.id &&
                            updateOauthClientSecretByIdMutation.isLoading ? (
                              <span
                                className="spinner-border spinner-border-sm me-2"
                                role="status"
                                aria-hidden="true"
                              ></span>
                            ) : (
                              <i className="bi bi-shield-lock me-2"></i>
                            )}
                            {t('resetSecret')}
                          </button>

                          <button
                            disabled={
                              currentId === item.id &&
                              deleteOauthClientMutation.isLoading
                            }
                            onClick={onClickRemove.bind(this, item)}
                            type="button"
                            className="btn btn-light"
                          >
                            {currentId === item.id &&
                            deleteOauthClientMutation.isLoading ? (
                              <span
                                className="spinner-border spinner-border-sm me-2"
                                role="status"
                                aria-hidden="true"
                              ></span>
                            ) : (
                              <i className="bi bi-trash me-2"></i>
                            )}
                            {t('deleteApp')}
                          </button>
                        </div>
                        <>
                          {isOpenAppSecret &&
                            queryOauthClientSecretByIdQuery.data && (
                              <div>
                                <p className="text-secondary user-select-all cursor-copy text-decoration-underline-hover">
                                  {queryOauthClientSecretByIdQuery.data}
                                </p>
                                <div className="user-select-none form-text text-muted">
                                  <i className="bi bi-question-circle me-2 text-warning"></i>
                                  {t('appSecret')}
                                </div>
                              </div>
                            )}

                          {isOpenAppSecret &&
                            queryOauthClientSecretByIdQuery.error && (
                              <div>
                                <p className="text-danger">
                                  {t('failToGetSecret')}
                                </p>
                              </div>
                            )}
                        </>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>

          {queryOauthClientsByUserQuery.data.length === 0 && (
            <div className="text-muted text-center my-4">
              <span>{t('noAppAvailable')}</span>（
              <span
                className="link-primary text-decoration-underline-hover cursor-pointer"
                onClick={onClickCreateApp}
              >
                {t('startCreateApp')}
              </span>
              ）
            </div>
          )}
        </div>
      </div>
    );
  }

  if (queryOauthClientsByUserQuery.error) {
    return <ErrorPage error={queryOauthClientsByUserQuery.error} />;
  }

  return <LoadPage />;
};
